package cn.com.blueInfo.security.config;

import cn.com.blueInfo.core.entity.CurrentLoginUserInfo;
import cn.com.blueInfo.core.param.SecurityParam;
import cn.com.blueInfo.core.util.JwtUtils;
import cn.com.blueInfo.security.filter.SecurityAuthenticationFilter;
import cn.com.blueInfo.security.service.JwtAuthenticationEntryPoint;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;

import java.util.Arrays;
import java.util.Collections;

@Configuration
public class SecurityConfig {

    @Autowired
    private SecurityParam securityParam;

    @Autowired
    private JwtUtils jwtUtils;

    @Autowired
    private CurrentLoginUserInfo currentLoginUserInfo;

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
            .cors(cors -> cors.configurationSource(corsConfigurationSource()))
                .csrf().disable()
                // 目前已存在多因素校验+持续token验证，所以暂时先不再开启csrf认证。后续如有需要再开启
//            .csrf(csrf -> csrf.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
//                    .ignoringAntMatchers(securityParam.getIgnored())
//            )
                .authorizeRequests()
                .antMatchers(securityParam.getIgnored()).permitAll() // 公开访问的路径
                .anyRequest().authenticated()
            .and()
                .exceptionHandling(ex -> ex.authenticationEntryPoint(new JwtAuthenticationEntryPoint()))
                // 采用自定义token验证，并在UsernamePasswordAuthenticationFilter之前执行
                .addFilterBefore(new SecurityAuthenticationFilter(jwtUtils, currentLoginUserInfo, securityParam),
                        UsernamePasswordAuthenticationFilter.class)
                .formLogin()
                .loginPage(loginPageUri()) // 指定自定义登录页面的路径
                .permitAll() // 允许所有人访问登录页面
            .and()
                .logout()
                .permitAll(); // 允许所有人访问登出页面
        return http.build();
    }

    @Bean
    CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        // 保持原有灵活的源模式配置
        for (String oneCorsHost : securityParam.getCorsHost()) {
            configuration.addAllowedOriginPattern(oneCorsHost);
        }

        configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE", "OPTIONS"));
        configuration.setAllowCredentials(true); // 允许携带 Cookie
        configuration.addAllowedHeader("*"); // 允许所有请求头
        configuration.setExposedHeaders(Collections.singletonList("Authorization"));
        configuration.setMaxAge(3600L); // 预检请求缓存时间

        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    private String loginPageUri() {
//        return "/api/auth/authorize" +
//                "?client_id=" + securityParam.getClientId() +
//                "&redirect_uri=" + securityParam.getRedirectUri() +
//                "&scope=" +
//                "&state=" + securityParam.getState();
        return "http://localhost:5173/login";
    }

}
